package src;

import java.util.*;

import pjwstk.jps.ast.*;
import pjwstk.jps.ast.auxname.*;
import pjwstk.jps.ast.binary.*;
import pjwstk.jps.ast.terminal.*;
import pjwstk.jps.ast.unary.*;

import pjwstk.jps.interpreter.qres.QResStack;
import pjwstk.jps.result.*;

/**
 * @author s9111_s10304
 *
 */
public class Main2
{
    @SuppressWarnings("unused")
    public static void main(String[] args) {
        
        // AST1: (bag(1, 2.1), bag(3+4, "test")) as nazwa;
        Expression expressionX = new Expression(
            new AsExpression(
                new CommaExpression(
                    new BagExpression(
                        new CommaExpression(
                            new IntegerTerminal(1),
                            new DoubleTerminal(2.1)
                        )
                    ),
                    new BagExpression(
                        new CommaExpression(
                            new PlusExpression(
                                new IntegerTerminal(3),
                                new IntegerTerminal(4)
                            ),
                            new NameTerminal("test")
                        )
                    )
                ),
                new NameTerminal("nazwa").getName()
            ));

        // QRES1: (bag(1, 2.1), bag(3+4, "test")) as nazwa;
        QResStack qres1 = new QResStack(); // ||
        
        qres1.push(new IntegerResult(1));  // || 1
        qres1.push(new DoubleResult(2.1)); // || 1 | 2.1
        
        ISingleResult isresR11 = (DoubleResult)qres1.pop();  // || 1
        ISingleResult isresL11 = (IntegerResult)qres1.pop(); // ||
        
        List<ISingleResult> structList11 = new ArrayList<ISingleResult>();
        structList11.add(isresL11);
        structList11.add(isresR11);
        StructResult structRes11 = new StructResult(structList11);
        qres1.push(structRes11); // || struct(1, 2.1)
        
        StructResult structRes12 = (StructResult)qres1.pop(); // || 
        
        Collection<ISingleResult> bagCol11 = new ArrayList<ISingleResult>();
        bagCol11.add(structRes12.elements().get(0));
        bagCol11.add(structRes12.elements().get(1));
        BagResult bagRes11 = new BagResult(bagCol11);
        qres1.push(bagRes11); // || bag(1, 2.1)
        
        qres1.push(new IntegerResult(3)); // || bag(1, 2.1) | 3
        qres1.push(new IntegerResult(4)); // || bag(1, 2.1) | 3 | 4
        
        IntegerResult plusRight11 = (IntegerResult)qres1.pop(); // || bag(1, 2.1) | 3
        IntegerResult plusLeft11 = (IntegerResult)qres1.pop();  // || bag(1, 2.1)
        IntegerResult plusRes11 = new IntegerResult(plusLeft11.getValue() + plusRight11.getValue());
        
        qres1.push(plusRes11); // || bag(1, 2.1) | 7
        qres1.push(new StringResult("test")); // || bag(1, 2.1) | 7 | "test"
        
        ISingleResult isresR12 = (StringResult)qres1.pop();  // || bag(1, 2.1) | 7
        ISingleResult isresL12 = (IntegerResult)qres1.pop(); // || bag(1, 2.1)
        
        List<ISingleResult> structList12 = new ArrayList<ISingleResult>();
        structList12.add(isresL12);
        structList12.add(isresR12);
        StructResult structRes13 = new StructResult(structList12);
        
        qres1.push(structRes13); // || bag(1, 2.1) | struct(7, "test")
        
        StructResult structRes14 = (StructResult)qres1.pop(); // || bag(1, 2.1)
        
        Collection<ISingleResult> bagCol12 = new ArrayList<ISingleResult>();
        bagCol12.add(structRes14.elements().get(0));
        bagCol12.add(structRes14.elements().get(1));
        BagResult bagRes12 = new BagResult(bagCol12);
        
        qres1.push(bagRes12); // || bag(1, 2.1) | bag(7, "test")
        
        BagResult bagResR11 = (BagResult)qres1.pop(); // || bag(1, 2.1)
        BagResult bagResL11 = (BagResult)qres1.pop(); // ||
        
        ArrayList<ISingleResult> bagColL11 = (ArrayList<ISingleResult>) bagResL11.getElements();
        ArrayList<ISingleResult> bagColR11 = (ArrayList<ISingleResult>) bagResR11.getElements();
        
        IntegerResult leftElem11 = (IntegerResult) bagColL11.get(0);  // 1
        DoubleResult leftElem12 = (DoubleResult) bagColL11.get(1);    // 2.1
        IntegerResult rightElem11 = (IntegerResult) bagColR11.get(0); // 7
        StringResult rightElem12 = (StringResult) bagColR11.get(1);   // "test"
        
        List<ISingleResult> structList13 = new ArrayList<ISingleResult>();
        structList13.add(leftElem11);
        structList13.add(rightElem11);
        
        List<ISingleResult> structList14 = new ArrayList<ISingleResult>();
        structList14.add(leftElem11);
        structList14.add(rightElem12);
        
        List<ISingleResult> structList15 = new ArrayList<ISingleResult>();
        structList15.add(leftElem12);
        structList15.add(rightElem11);
        
        List<ISingleResult> structList16 = new ArrayList<ISingleResult>();
        structList16.add(leftElem12);
        structList16.add(rightElem12);
        
        StructResult structRes15 = new StructResult(structList13); // struct(1, 7)
        StructResult structRes16 = new StructResult(structList14); // struct(1, "test")
        StructResult structRes17 = new StructResult(structList15); // struct(2.1, 7)
        StructResult structRes18 = new StructResult(structList16); // struct(2.1, "test")
        
        Collection<ISingleResult> bagCol13 = new ArrayList<ISingleResult>();
        bagCol13.add(structRes15);
        bagCol13.add(structRes16);
        bagCol13.add(structRes17);
        bagCol13.add(structRes18);
        BagResult bagRes13 = new BagResult(bagCol13);
        
        qres1.push(bagRes13); // || bag(struct(1, 7), struct(1, "test"), struct(2.1, 7), struct(2.1, "test"))
        qres1.push(new StringResult("nazwa")); // || bag(struct(1, 7), struct(1, "test"), struct(2.1, 7), struct(2.1, "test")) | "nazwa"
        
        ISingleResult isresR13 = (StringResult)qres1.pop(); // || bag(struct(1, 7), struct(1, "test"), struct(2.1, 7), struct(2.1, "test"))
        BagResult bagResL12 = (BagResult)qres1.pop(); // ||
        
        BinderResult binRes11 = new BinderResult(((StringResult)isresR13).getValue(), bagResL12);
        
        qres1.push(binRes11); // || nazwa(bag(struct(1, 7), struct(1, "test"), struct(2.1, 7), struct(2.1, "test")))

        System.out.println("QRES1: " + qres1.peek().toString());
        

        // AST2: (bag("ala", "ma", "kota"), (8*10, false));
        Expression expressionY = new Expression(
            new CommaExpression(
                new BagExpression(
                    new CommaExpression(
                        new CommaExpression(
                            new NameTerminal("ala"),
                            new NameTerminal("ma")
                        ),
                        new NameTerminal("kota")
                    )
                ),
                new CommaExpression(
                    new MultiplyExpression(
                        new IntegerTerminal(8),
                        new IntegerTerminal(10)
                    ),
                    new BooleanTerminal(false)
                )
            ));
        
        // QRES2: (bag("ala", "ma", "kota"), (8*10, false));
        QResStack qres2 = new QResStack();
        
        qres2.push(new StringResult("ala")); // || "ala"
        qres2.push(new StringResult("ma"));  // || "ala" | "ma"
        
        StringResult stringResR21 = (StringResult) qres2.pop(); // || "ala"
        StringResult stringResL21 = (StringResult) qres2.pop(); // ||
        
        List<ISingleResult> structList21 = new ArrayList<ISingleResult>();
        structList21.add((StringResult)stringResL21);
        structList21.add((StringResult)stringResR21);
        StructResult structRes21 = new StructResult(structList21);
        
        qres2.push(structRes21); // || struct("ala", "ma")
        qres2.push(new StringResult("kota")); // || struct("ala", "ma") | "kota"
        
        StringResult stringResR22 = (StringResult) qres2.pop(); // || struct("ala", "ma")
        StructResult structResL21 = (StructResult) qres2.pop(); // ||
        
        List<ISingleResult> structList22 = new ArrayList<ISingleResult>();
        structList22.add((StringResult) structResL21.elements().get(0)); // "ala"
        structList22.add((StringResult) structResL21.elements().get(1)); // "ma"
        structList22.add((StringResult) stringResR22); // "kota"
        StructResult structRes22 = new StructResult(structList22);
        
        qres2.push(structRes22); // || struct("ala", "ma", "kota")
        
        StructResult structRes23 = (StructResult) qres2.pop(); // ||
        
        Collection<ISingleResult> bagCol21 = new ArrayList<ISingleResult>();
        bagCol21.add(structRes23.elements().get(0)); // "ala"
        bagCol21.add(structRes23.elements().get(1)); // "ma"
        bagCol21.add(structRes23.elements().get(2)); // "kota" 
        BagResult bagRes21 = new BagResult(bagCol21);
        
        qres2.push(bagRes21); // || bag("ala", "ma", "kota")
        qres2.push(new IntegerResult(8));  // || bag("ala", "ma", "kota") | 8
        qres2.push(new IntegerResult(10)); // || bag("ala", "ma", "kota") | 8 | 10
        
        IntegerResult integerResR21 = (IntegerResult)qres2.pop();
        IntegerResult integerResL21 = (IntegerResult)qres2.pop();
        
        IntegerResult multiRes21 = new IntegerResult(integerResL21.getValue() * integerResR21.getValue());
        
        qres2.push(multiRes21); // || bag("ala", "ma", "kota") | 80
        qres2.push(new BooleanResult(false)); // || bag("ala", "ma", "kota") | 80 | false
        
        BooleanResult boolResR21 = (BooleanResult)qres2.pop();  // || bag("ala", "ma", "kota") | 80
        IntegerResult multiResL21 = (IntegerResult)qres2.pop(); // || bag("ala", "ma", "kota")
        
        List<ISingleResult> structList23 = new ArrayList<ISingleResult>();
        structList23.add(multiResL21);
        structList23.add(boolResR21);
        StructResult structRes24 = new StructResult(structList23);
        
        qres2.push(structRes24); // || bag("ala", "ma", "kota") | struct(80, false)
        
        StructResult structRes25 = (StructResult) qres2.pop(); // || bag("ala", "ma", "kota")
        BagResult bagRes22 = (BagResult)qres2.pop(); // ||
        
        ArrayList<ISingleResult> bagCol22 = (ArrayList<ISingleResult>) bagRes22.getElements();
        StringResult stringRes21 = (StringResult) bagCol22.get(0);
        StringResult stringRes22 = (StringResult) bagCol22.get(1);
        StringResult stringRes23 = (StringResult) bagCol22.get(2);
        
        List<ISingleResult> structList24 = new ArrayList<ISingleResult>();
        structList24.add((StringResult) stringRes21); // "ala"
        structList24.add((IntegerResult) structRes25.elements().get(0)); // 80
        structList24.add((BooleanResult) structRes25.elements().get(1)); // false
        StructResult structRes26 = new StructResult(structList24); // struct("ala", 80, false)
  
        List<ISingleResult> structList25 = new ArrayList<ISingleResult>();
        structList25.add((StringResult) stringRes22); // "ma"
        structList25.add((IntegerResult) structRes25.elements().get(0)); // 80
        structList25.add((BooleanResult) structRes25.elements().get(1)); // false
        StructResult structRes27 = new StructResult(structList25); // struct("ma", 80, false)
        
        List<ISingleResult> structList26 = new ArrayList<ISingleResult>();
        structList26.add((StringResult) stringRes23); // "kota"
        structList26.add((IntegerResult) structRes25.elements().get(0)); // 80
        structList26.add((BooleanResult) structRes25.elements().get(1)); // false
        StructResult structRes28 = new StructResult(structList26); // struct("kota", 80, false)
        
        Collection<ISingleResult> bagCol23 = new ArrayList<ISingleResult>();
        bagCol23.add(structRes26);
        bagCol23.add(structRes27);
        bagCol23.add(structRes28);
        BagResult bagRes23 = new BagResult(bagCol23);
        
        qres2.push(bagRes23); // || bag(struct("ala", 80, false), struct("ma", 80, false), struct("kota", 80, false))
        
        System.out.println("QRES2: " + qres2.peek().toString());
        
        
        // AST3: (((bag("JPS", "rules")) groupas x), 2.2, true)
        Expression expressionZ = new Expression(
            new CommaExpression(
                new CommaExpression(
                    new GroupAsExpression(
                        new BagExpression(
                            new CommaExpression(
                                new NameTerminal("JPS"),
                                new NameTerminal("rules")
                            )
                        ),
                        new NameTerminal("JPS").getName()
                    ),
                    new DoubleTerminal(2.2)
                ),
                new BooleanTerminal(true)
            ));
        
        // QRES3: (((bag("JPS", "rules")) groupas x), 2.2, true)
        QResStack qres3 = new QResStack();
        
        qres3.push(new StringResult("JPS"));   // || "JPS"
        qres3.push(new StringResult("rules")); // || "JPS" | "rules"
        
        StringResult stringResR31 = (StringResult)qres3.pop(); // || "JPS"
        StringResult stringResL31 = (StringResult)qres3.pop(); // ||
        
        List<ISingleResult> structList31 = new ArrayList<ISingleResult>();
        structList31.add(stringResL31);
        structList31.add(stringResR31);
        StructResult structRes31 = new StructResult(structList31);
        
        qres3.push(structRes31); // || struct("JPS", "rules")
        
        StructResult structRes32 = (StructResult)qres3.pop(); // ||
        
        Collection<ISingleResult> bagCol31 = new ArrayList<ISingleResult>();
        bagCol31.add(structRes32.elements().get(0));
        bagCol31.add(structRes32.elements().get(1));
        BagResult bagRes31 = new BagResult(bagCol31);
        
        qres3.push(bagRes31); // || bag("JPS", "rules")
        qres3.push(new StringResult("x")); // || bag("JPS", "rules") | "x"
        
        StringResult stringRes31 = (StringResult)qres3.pop(); // || bag("JPS", "rules")
        BagResult bagRes32 = (BagResult)qres3.pop(); // ||
        
        BinderResult binderRes31 = new BinderResult(stringRes31.getValue(), bagRes32);
        
        qres3.push(binderRes31); // || x(bag("JPS", "rules"))
        qres3.push(new DoubleResult(2.2)); // || x(bag("JPS", "rules")) | 2.2
        
        DoubleResult doubleRes31 = (DoubleResult)qres3.pop(); // || x(bag("JPS", "rules"))
        BinderResult binderRes32 = (BinderResult)qres3.pop(); // ||
        
        List<ISingleResult> structList32 = new ArrayList<ISingleResult>();
        structList32.add(binderRes32);
        structList32.add(doubleRes31);
        StructResult structRes33 = new StructResult(structList32);
        
        qres3.push(structRes33); // || struct(x(bag("JPS", "rules")), 2.2)
        qres3.push(new BooleanResult(true)); // || struct(x(bag("JPS", "rules")), 2.2) | true
        
        BooleanResult boolRes31 = (BooleanResult)qres3.pop(); // || struct(, 2.2)
        StructResult structRes34 = (StructResult)qres3.pop(); // ||
        
        List<ISingleResult> structList33 = new ArrayList<ISingleResult>();
        structList33.add((BinderResult) structRes34.elements().get(0)); // x(bag("JPS", "rules"))
        structList33.add((DoubleResult) structRes34.elements().get(1)); // 2.2
        structList33.add((BooleanResult) boolRes31); // true
        StructResult structRes35 = new StructResult(structList33);
        
        qres3.push(structRes35); // || struct(x(bag("JPS", "rules")), 2.2, true)
        
        System.out.println("QRES3: " + qres3.peek().toString());
    }
}